﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Sio.Mdm.Entities
{
    /// <summary>
    /// Enumeration of possible entity states
    /// </summary>
    public enum EntityState : int
    {
        /// <summary>
        /// Entity has not changed since last load
        /// </summary>
        Unchanged,
        /// <summary>
        /// Entity was just created and not saved yet
        /// </summary>
        Created = 1,
        /// <summary>
        /// Entity was loaded and changed
        /// </summary>
        Changed = 2,
        /// <summary>
        /// Entity was deleted
        /// </summary>
        Deleted = 4,
        /// <summary>
        /// Entity is has error specified
        /// </summary>
        /// <seealso cref="Error"/>
        Error = 8,
        /// <summary>
        /// Only entity instance was created and entity was not loaded or created yet
        /// </summary>
        Unknown = 16
    }

    /// <summary>
    /// Interface of functions every entity should implement
    /// </summary>
    public interface IEntity
    {   
        /// <summary>
        /// Entity state
        /// </summary>
        /// <seealso cref="EntityState"/>
        EntityState EntityState { get; }
        /// <summary>
        /// Possible error returned by buisness logic
        /// </summary>
        Sio.Mdm.Types.Result Error { get; }
        /// <summary>
        /// Get fields defined in entity
        /// </summary>
        string[] FieldsName { get; }
        /// <summary>
        /// Create entity in storage
        /// </summary>
        /// <returns>True if entity was created</returns>
        bool Create();
        /// <summary>
        /// Delete entity from storage
        /// </summary>
        /// <returns>True if entity was deleted</returns>
        /// <seealso cref="Error"/>
        bool Delete();
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="critera"></param>
        /// <returns></returns>
        bool Load<T>(ISioFilter<T> critera);
        /// <summary>
        /// Update changes of entity to storage
        /// </summary>
        /// <returns>True if entity was updated</returns>
        /// <seealso cref="Error"/>
        bool Update();

        /// <summary>
        /// Set field value
        /// </summary>
        /// <param name="name">Name of field</param>
        /// <param name="value">Value to be set</param>
        void SetField(string name, object value);
        /// <summary>
        /// Get field value
        /// </summary>
        /// <param name="name">Name of field to get value for</param>
        /// <returns>Value of field</returns>
        object GetField(string name);
        /// <summary>
        /// Get field value converted to passed type
        /// </summary>
        /// <typeparam name="T">Type to retreive</typeparam>
        /// <param name="name">Name of field to retreive value for</param>
        /// <returns>Value of field</returns>
        T GetField<T>(string name);

        /// <summary>
        /// Set state of entity. Usually yout should not call this function directly.
        /// </summary>
        /// <param name="state"><see cref="EntityState"/></param>
        void SetState(EntityState state);

        /// <summary>
        /// Validate entity state
        /// </summary>
        /// <returns>True if entity is valid</returns>
        /// <seealso cref="ValidationAttribute"/>
        /// <seealso cref="NullOrEmptyValidationAttribute"/>
        /// <seealso cref="RegexValidationAttribute"/>
        /// <see cref="RangeValidationAttribute"/>
        /// <seealso cref="ServiceValidationAttribute"/>
        bool Validate();

        /// <summary>
        /// Changed fields with old values
        /// </summary>
        /// <returns></returns>
        Dictionary<string, object> GetOldValues();
    }
}
